import { RefObject } from 'react';
import { Keyboard, ScrollView } from 'react-native';
import { ClientRole } from 'react-native-agora';

import { Dispatch, LoginParams, State } from './types';
import { LoginApi } from '../../api';
import { setUserInfo, getUserInfo } from '../../store/user';
import navigator from '../../util/navigator';
import { initEngine, setClientRole } from '../../util/RTC/rtcEngine';
import { UserRole } from '../ClassRoom/constant';
import { getScreenInfo } from '../../util/screen';
import { LOGIN_TYPE } from './constant';
import LoginUtils from './utils';
import { toolTipOpen } from '../../util/global';
import { inAppPurchaseModule, shellExec } from '../../util/native';
import { DEVICE_ID } from '../../constant';
import { phonePx } from '../../util/adapt';

let dispatch: Dispatch;
let state: State;
let loginScroll: RefObject<ScrollView>;
let verifyInput: RefObject<any>;
let isPasswordView = true;
let interval: NodeJS.Timer;

const { width } = getScreenInfo({});

export default (d: Dispatch, s: State): void => {
  dispatch = d;
  state = s;
};

export const sendVerifyCode = (): void => {
  dispatch({ type: 'SEND_VERIFY_CODE' });
};

export const sendVerifyCodeFinish = (): void => {
  dispatch({ type: 'SEND_VERIFY_CODE_FINISH' });
};

export const countdownVerifyCode = (value: number): void => {
  dispatch({ type: 'COUNTDOWN_VERIFY_CODE', value });
};

export const setPhoneNumber = (value: string): void => {
  dispatch({ type: 'SET_PHONE_NUMBER', value });
};

export const setVerifyCode = (value: string): void => {
  dispatch({ type: 'SET_VERIFY_CODE', value });
};

export const setHasShownAlert = (value: boolean): void => {
  dispatch({ type: 'SET_HAS_SHOWN_ALERT', value });
};

export const setPassword = (value: string): void => {
  dispatch({ type: 'SET_PASSWORD', value });
};

export const setIsShowPassword = (value: boolean): void => {
  dispatch({ type: 'SET_IS_SHOW_PASSWORD', value });
};

export const setLoginType = (value: LOGIN_TYPE): void => {
  dispatch({ type: 'SET_LOGIN_TYPE', value });
};

export const setIsBind = (value: boolean): void => {
  dispatch({ type: 'SET_IS_BIND', value });
};

export const setShowAgreement = (value: boolean): void => {
  dispatch({ type: 'SET_SHOW_AGREEMENT', value });
};

const visitInputPassword = (): void => {
  Keyboard.dismiss();
  if (loginScroll && loginScroll.current) {
    loginScroll.current.scrollTo({
      x: phonePx(320),
      y: 0,
      animated: true
    });
    isPasswordView = true;
  }
};

const visitInputVerify = (): void => {
  Keyboard.dismiss();
  if (loginScroll && loginScroll.current) {
    loginScroll.current.scrollTo({
      x: 0,
      y: 0,
      animated: true
    });
    isPasswordView = false;
  }
};

export const setScroll = (scroll: RefObject<ScrollView>): void => {
  loginScroll = scroll;
};

export const setVerifyInput = (input: RefObject<any>): void => {
  verifyInput = input;
};

export const clearVerifyInterval = (): void => {
  clearInterval(interval);
};

export const handleBackButton = (): boolean => {
  if (!isPasswordView) {
    visitInputVerify();
    return true;
  }
  return false;
};

export const clickPasswordLogin = (): void => {
  setLoginType(LOGIN_TYPE.Password);
  visitInputPassword();
  setPassword('');
};

export const clickVerifyLogin = (): void => {
  setLoginType(LOGIN_TYPE.Verify);
  visitInputVerify();
  setVerifyCode('');
};

// 点击获取验证码
export const clickGetVerifyCode = (): void => {
  const { phoneNumber } = state;

  if (LoginUtils.invalidatePhone(phoneNumber)) {
    toolTipOpen({ desc: '手机号格式不正确' });
    return;
  }
  sendVerifyCode();
  LoginApi.getVerifyCode({
    mobilePhone: phoneNumber
  })
    .then((res): void => {
      if (res.code === 0) {
        let totalTime = 60;

        if (verifyInput && verifyInput.current) {
          verifyInput.current.focus();
        }

        interval = setInterval((): void => {
          totalTime -= 1;
          if (totalTime === 0) {
            clearInterval(interval);
            sendVerifyCodeFinish();
            return;
          }
          countdownVerifyCode(totalTime);
        }, 1000);
      } else {
        clearInterval(interval);
        sendVerifyCodeFinish();
      }
    })
    .catch((): void => {
      clearInterval(interval);
      sendVerifyCodeFinish();
    });
};

// 进入相关页面
export const openView = (): void => {
  clearVerifyInterval();
  const { token } = getUserInfo();

  if (!token) {
    navigator.replace('Login');
    return;
  }

  navigator.replace('TabNav');
};

export const loginAction = ({
  userId,
  token,
  userRole,
  nickName,
  headUrl,
  isGuest = false
}: LoginParams): void => {
  setUserInfo({
    userId: String(userId),
    token,
    role: userRole,
    nickName,
    headUrl,
    isGuest
  });
  // 初始化RTC引擎
  initEngine({
    uid: Number(userId),
    role:
      userRole === UserRole.Student || userRole === UserRole.Assist
        ? ClientRole.Broadcaster
        : ClientRole.Audience
  });
  openView();
  shellExec.makeSureLongLinkConnected();

  inAppPurchaseModule.startTransactionObservingAndPaymentTransactionVerifingWithUserID(
    userId
  );
};

export const loginWithVerifyCode = (): void => {
  Keyboard.dismiss();
  const { phoneNumber, verifyCode } = state;
  LoginApi.loginWithVerifyCode({ mobilePhone: phoneNumber, verifyCode }).then(
    (res): void => {
      const { code, data } = res;
      if (code === 0) {
        loginAction(data);
      }
    }
  );
};

export const loginWithPassword = (): void => {
  Keyboard.dismiss();
  const { phoneNumber, password } = state;
  LoginApi.loginWithPassword({
    mobilePhone: phoneNumber,
    passwd: password
  }).then((res): void => {
    const { code, data } = res;
    if (code === 0) {
      loginAction(data);
    }
  });
};

export const guestLogin = async (): Promise<void> => {
  const res = await LoginApi.guestLogin({ deviceId: DEVICE_ID });
  if (res.code === 0) {
    loginAction({ ...res.data, isGuest: true });
  }
};

export const guestBindMobilePhone = async (): Promise<void> => {
  Keyboard.dismiss();
  const { phoneNumber, verifyCode } = state;
  const { userId } = getUserInfo();

  const res = await LoginApi.guestBindMobilePhone({
    userId,
    mobilePhone: phoneNumber,
    verifyCode
  });
  if (res.code === 0) {
    setUserInfo({ isGuest: false, role: UserRole.Student });
    setClientRole(ClientRole.Broadcaster);
    navigator.goBack();
  }
};
